home *** CD-ROM | disk | FTP | other *** search
/ Clickx 115 / Clickx 115.iso / software / tools / windows / tails-i386-0.16.iso / live / filesystem.squashfs / usr / share / perl5 / Devel / PartialDump.pm
Encoding:
Perl POD Document  |  2010-01-08  |  12.0 KB  |  634 lines

  1. #!/usr/bin/perl
  2.  
  3. package Devel::PartialDump;
  4. use Moose;
  5.  
  6. use Carp ();
  7. use Scalar::Util qw(looks_like_number reftype blessed);
  8.  
  9. use namespace::clean -except => 'meta';
  10.  
  11. our $VERSION = "0.13";
  12.  
  13. use Sub::Exporter -setup => {
  14.     exports => [qw(dump warn show show_scalar croak carp confess cluck $default_dumper)],
  15.     groups => {
  16.         easy => [qw(dump warn show show_scalar carp croak)],
  17.         carp => [qw(croak carp)],
  18.     },
  19.     collectors => {
  20.         override_carp => sub {
  21.             no warnings 'redefine';
  22.             require Carp::Heavy;
  23.             *Carp::caller_info = \&replacement_caller_info;
  24.         },
  25.     },
  26. };
  27.  
  28. # a replacement for Carp::caller_info
  29. sub replacement_caller_info {
  30.     my $i = shift(@_) + 1;
  31.  
  32.     package DB;
  33.     my %call_info;
  34.     @call_info{
  35.     qw(pack file line sub has_args wantarray evaltext is_require)
  36.     } = caller($i);
  37.  
  38.     return unless (defined $call_info{pack});
  39.  
  40.     my $sub_name = Carp::get_subname(\%call_info);
  41.  
  42.     if ($call_info{has_args}) {
  43.         $sub_name .= '(' . Devel::PartialDump::dump(@DB::args) . ')';
  44.     }
  45.  
  46.     $call_info{sub_name} = $sub_name;
  47.  
  48.     return wantarray() ? %call_info : \%call_info;
  49. }
  50.  
  51.  
  52. has max_length => (
  53.     isa => "Int",
  54.     is  => "rw",
  55.     predicate => "has_max_length",
  56.     clearer => "clear_max_length",
  57. );
  58.  
  59. has max_elements => (
  60.     isa => "Int",
  61.     is  => "rw",
  62.     default => 6,
  63.     predicate => "has_max_elements",
  64.     clearer => "clear_max_elements",
  65. );
  66.  
  67. has max_depth => (
  68.     isa => "Int",
  69.     is  => "rw",
  70.     required => 1,
  71.     default => 2,
  72. );
  73.  
  74. has stringify => (
  75.     isa => "Bool",
  76.     is  => "rw",
  77.     default => 0,
  78. );
  79.  
  80. has pairs => (
  81.     isa => "Bool",
  82.     is  => "rw",
  83.     default => 1,
  84. );
  85.  
  86. has objects => (
  87.     isa => "Bool",
  88.     is  => "rw",
  89.     default => 1,
  90. );
  91.  
  92. has list_delim => (
  93.     isa => "Str",
  94.     default => ", ",
  95.     is => "rw",
  96. );
  97.  
  98. has pair_delim => (
  99.     isa => "Str",
  100.     #default => " => ",
  101.     default => ": ",
  102.     is => "rw",
  103. );
  104.  
  105. sub warn_str {
  106.     my ( @args ) = @_;
  107.     my $self;
  108.  
  109.     if ( blessed($args[0]) and $args[0]->isa(__PACKAGE__) ) {
  110.         $self = shift @args;
  111.     } else {
  112.         $self = our $default_dumper;
  113.     }
  114.     return $self->_join(
  115.         map {
  116.             !ref($_) && defined($_)
  117.             ? $_
  118.             : $self->dump($_)
  119.         } @args
  120.     );
  121. }
  122.  
  123. sub warn {
  124.     Carp::carp(warn_str(@_));
  125. }
  126.  
  127. foreach my $f ( qw(carp croak confess cluck) ) {
  128.     no warnings 'redefine';
  129.     eval "sub $f {
  130.         local \$Carp::CarpLevel = \$Carp::CarpLevel + 1;
  131.         Carp::$f(warn_str(\@_));
  132.     }";
  133. }
  134.  
  135. sub show {
  136.     my ( @args ) = @_;
  137.     my $self;
  138.  
  139.     if ( blessed($args[0]) and $args[0]->isa(__PACKAGE__) ) {
  140.         $self = shift @args;
  141.     } else {
  142.         $self = our $default_dumper;
  143.     }
  144.  
  145.     $self->warn(@args);
  146.  
  147.     return ( @args == 1 ? $args[0] : @args );
  148. }
  149.  
  150. sub show_scalar ($) { goto \&show }
  151.  
  152. sub _join {
  153.     my ( $self, @strings ) = @_;
  154.  
  155.     my $ret = "";
  156.  
  157.     if ( @strings ) {
  158.         my $sep = $, || $" || " ";
  159.         my $re = qr/(?: \s| \Q$sep\E )$/x;
  160.  
  161.         my $last = pop @strings;
  162.  
  163.         foreach my $string ( @strings ) {
  164.             $ret .= $string;
  165.             $ret .= $sep unless $string =~ $re;
  166.         }
  167.  
  168.         $ret .= $last;
  169.     }
  170.  
  171.     return $ret;
  172. }
  173.  
  174. sub dump {
  175.     my ( @args ) = @_;
  176.     my $self;
  177.  
  178.     if ( blessed($args[0]) and $args[0]->isa(__PACKAGE__) ) {
  179.         $self = shift @args;
  180.     } else {
  181.         $self = our $default_dumper;
  182.     }
  183.  
  184.     my $method = "dump_as_" . ( $self->should_dump_as_pairs(@args) ? "pairs" : "list" );
  185.  
  186.     my $dump = $self->$method(1, @args);
  187.  
  188.     if ( $self->has_max_length ) {
  189.         if ( length($dump) > $self->max_length ) {
  190.             $dump = substr($dump, 0, $self->max_length - 3) . "...";
  191.         }
  192.     }
  193.  
  194.     if ( not defined wantarray ) {
  195.         CORE::warn "$dump\n";
  196.     } else {
  197.         return $dump;
  198.     }
  199. }
  200.  
  201. sub should_dump_as_pairs {
  202.     my ( $self, @what ) = @_;
  203.  
  204.     return unless $self->pairs;
  205.  
  206.     return if @what % 2 != 0; # must be an even list
  207.  
  208.     for ( my $i = 0; $i < @what; $i += 2 ) {
  209.         return if ref $what[$i]; # plain strings are keys
  210.     }
  211.  
  212.     return 1;
  213. }
  214.  
  215. sub dump_as_pairs {
  216.     my ( $self, $depth, @what ) = @_;
  217.  
  218.     my $truncated;
  219.     if ( $self->has_max_elements and ( @what / 2 ) > $self->max_elements ) {
  220.         $truncated = 1;
  221.         @what = splice(@what, 0, $self->max_elements * 2 );
  222.     }
  223.  
  224.     return join($self->list_delim, $self->_dump_as_pairs($depth, @what), ($truncated ? "..." : ()) );
  225. }
  226.  
  227. sub _dump_as_pairs {
  228.     my ( $self, $depth, @what ) = @_;
  229.  
  230.     return unless @what;
  231.     
  232.     my ( $key, $value, @rest ) = @what;
  233.  
  234.     return (
  235.         ( $self->format_key($depth, $key) . $self->pair_delim . $self->format($depth, $value) ),
  236.         $self->_dump_as_pairs($depth, @rest),
  237.     );
  238. }
  239.  
  240. sub dump_as_list {
  241.     my ( $self, $depth, @what ) = @_;
  242.  
  243.     my $truncated;
  244.     if ( $self->has_max_elements and @what > $self->max_elements ) {
  245.         $truncated = 1;
  246.         @what = splice(@what, 0, $self->max_elements );
  247.     }
  248.  
  249.     return join( ", ", ( map { $self->format($depth, $_) } @what ), ($truncated ? "..." : ()) );
  250. }
  251.  
  252. sub format {
  253.     my ( $self, $depth, $value ) = @_;
  254.  
  255.     defined($value)
  256.         ? ( ref($value)
  257.             ? ( blessed($value)
  258.                 ? $self->format_object($depth, $value)
  259.                 : $self->format_ref($depth, $value) )
  260.             : ( looks_like_number($value)
  261.                 ? $self->format_number($depth, $value)
  262.                 : $self->format_string($depth, $value) ) )
  263.         : $self->format_undef($depth, $value),
  264. }
  265.  
  266. sub format_key {
  267.     my ( $self, $depth, $key ) = @_;
  268.     return $key;
  269. }
  270.  
  271. sub format_ref {
  272.     my ( $self, $depth, $ref ) = @_;
  273.  
  274.     if ( $depth > $self->max_depth ) {
  275.         return overload::StrVal($ref);
  276.     } else {
  277.         my $reftype = reftype($ref);
  278.         my $method = "format_" . lc reftype $ref;
  279.  
  280.         if ( $self->can($method) ) {
  281.             return $self->$method( $depth, $ref );
  282.         } else {
  283.             return overload::StrVal($ref);
  284.         }
  285.     }
  286. }
  287.  
  288. sub format_array {
  289.     my ( $self, $depth, $array ) = @_;
  290.  
  291.     my $class = blessed($array) || '';
  292.  
  293.     return $class . "[ " . $self->dump_as_list($depth + 1, @$array) . " ]";
  294. }
  295.  
  296. sub format_hash {
  297.     my ( $self, $depth, $hash ) = @_;
  298.  
  299.     my $class = blessed($hash) || '';
  300.  
  301.     return $class . "{ " . $self->dump_as_pairs($depth + 1, map { $_ => $hash->{$_} } sort keys %$hash) . " }";
  302. }
  303.  
  304. sub format_scalar {
  305.     my ( $self, $depth, $scalar ) = @_;
  306.  
  307.     my $class = blessed($scalar) || '';
  308.     $class .= "=" if $class;
  309.  
  310.     return $class . "\\" . $self->format($depth + 1, $$scalar);
  311. }
  312.  
  313. sub format_object {
  314.     my ( $self, $depth, $object ) = @_;
  315.  
  316.     if ( $self->objects ) {
  317.         return $self->format_ref($depth, $object);
  318.     } else {
  319.         return $self->stringify ? "$object" : overload::StrVal($object);
  320.     }
  321. }
  322.  
  323. sub format_string {
  324.     my ( $self, $depth, $str ) =@_;
  325.     # FIXME use String::Escape ?
  326.  
  327.     # remove vertical whitespace
  328.     $str =~ s/\n/\\n/g;
  329.     $str =~ s/\r/\\r/g;
  330.  
  331.     # reformat nonprintables
  332.     $str =~ s/(\P{IsPrint})/"\\x{" . sprintf("%x", ord($1)) . "}"/ge;
  333.  
  334.     $self->quote($str);
  335. }
  336.  
  337. sub quote {
  338.     my ( $self, $str ) = @_;
  339.  
  340.     qq{"$str"};
  341. }
  342.  
  343. sub format_undef { "undef" }
  344.  
  345. sub format_number {
  346.     my ( $self, $depth, $value ) = @_;
  347.     return "$value";
  348. }
  349.  
  350. our $default_dumper = __PACKAGE__->new;
  351.  
  352. __PACKAGE__
  353.  
  354. __END__
  355.  
  356. =pod
  357.  
  358. =head1 NAME
  359.  
  360. Devel::PartialDump - Partial dumping of data structures, optimized for argument
  361. printing.
  362.  
  363. =head1 SYNOPSIS
  364.  
  365.     use Devel::PartialDump;
  366.  
  367.     sub foo {
  368.         print "foo called with args: " . Devel::PartialDump->new->dump(@_);
  369.     }
  370.  
  371.     use Devel::PartialDump qw(warn);
  372.  
  373.     # warn is overloaded to create a concise dump instead of stringifying $some_bad_data
  374.     warn "this made a boo boo: ", $some_bad_data
  375.  
  376. =head1 DESCRIPTION
  377.  
  378. This module is a data dumper optimized for logging of arbitrary parameters.
  379.  
  380. It attempts to truncate overly verbose data, in a way that is hopefully more
  381. useful for diagnostics warnings than
  382.  
  383.     warn Dumper(@stuff);
  384.  
  385. Unlike other data dumping modules there are no attempts at correctness or cross
  386. referencing, this is only meant to provide a slightly deeper look into the data
  387. in question.
  388.  
  389. There is a default recursion limit, and a default truncation of long lists, and
  390. the dump is formatted on one line (new lines in strings are escaped), to aid in
  391. readability.
  392.  
  393. You can enable it temporarily by importing functions like C<warn>, C<croak> etc
  394. to get more informative errors during development, or even use it as:
  395.  
  396.     BEGIN { local $@; eval "use Devel::PartialDump qw(...)" }
  397.  
  398. to get DWIM formatting only if it's installed, without introducing a
  399. dependency.
  400.  
  401. =head1 SAMPLE OUTPUT
  402.  
  403. =over 4
  404.  
  405. =item C<< "foo" >>
  406.  
  407.     "foo"
  408.  
  409. =item C<< "foo" => "bar" >>
  410.  
  411.     foo: "bar"
  412.  
  413. =item C<< foo => "bar", gorch => [ 1, "bah" ] >>
  414.  
  415.     foo: "bar", gorch: [ 1, "bah" ]
  416.  
  417. =item C<< [ { foo => ["bar"] } ] >>
  418.  
  419.     [ { foo: ARRAY(0x9b265d0) } ]
  420.  
  421. =item C<< [ 1 .. 10 ] >>
  422.  
  423.     [ 1, 2, 3, 4, 5, 6, ... ]
  424.  
  425. =item C<< "foo\nbar" >>
  426.  
  427.     "foo\nbar"
  428.  
  429. =item C<< "foo" . chr(1) >>
  430.  
  431.     "foo\x{1}"
  432.  
  433. =back
  434.  
  435. =head1 ATTRIBUTES
  436.  
  437. =over 4
  438.  
  439. =item max_length
  440.  
  441. The maximum character length of the dump.
  442.  
  443. Anything bigger than this will be truncated.
  444.  
  445. Not defined by default.
  446.  
  447. =item max_elements
  448.  
  449. The maximum number of elements (array elements or pairs in a hash) to print.
  450.  
  451. Defualts to 6.
  452.  
  453. =item max_depth
  454.  
  455. The maximum level of recursion.
  456.  
  457. Defaults to 2.
  458.  
  459. =item stringify
  460.  
  461. Whether or not to let objects stringify themeslves, instead of using
  462. L<overload/StrVal> to avoid sideffects.
  463.  
  464. Defaults to false (no overloading).
  465.  
  466. =item pairs
  467.  
  468. Whether or not to autodetect named args as pairs in the main C<dump> function.
  469. If this attribute is true, and the top level value list is even sized, and
  470. every odd element is not a reference, then it will dumped as pairs instead of a
  471. list.
  472.  
  473. =back
  474.  
  475. =head1 EXPORTS
  476.  
  477. All exports are optional, nothing is exported by default.
  478.  
  479. This module uses L<Sub::Exporter>, so exports can be renamed, curried, etc.
  480.  
  481. =over 4
  482.  
  483. =item warn
  484.  
  485. =item show
  486.  
  487. =item show_scalar
  488.  
  489. =item croak
  490.  
  491. =item carp
  492.  
  493. =item confess
  494.  
  495. =item cluck
  496.  
  497. =item dump
  498.  
  499. See the various methods for behavior documentation.
  500.  
  501. These methods will use C<$Devel::PartialDump::default_dumper> as the invocant if the
  502. first argument is not blessed and C<isa> L<Devel::PartialDump>, so they can be
  503. used as functions too.
  504.  
  505. Particularly C<warn> can be used as a drop in replacement for the built in
  506. warn:
  507.  
  508.     warn "blah blah: ", $some_data;
  509.  
  510. by importing
  511.  
  512.     use Devel::PartialDump qw(warn);
  513.  
  514. C<$some_data> will be have some of it's data dumped.
  515.  
  516. =item $default_dumper
  517.  
  518. The default dumper object to use for export style calls.
  519.  
  520. Can be assigned to to alter behavior globally.
  521.  
  522. This is generally useful when using the C<warn> export as a drop in replacement
  523. for C<CORE::warn>.
  524.  
  525. =back
  526.  
  527. =head1 METHODS
  528.  
  529. =over 4
  530.  
  531. =item warn @blah
  532.  
  533. A warpper for C<dump> that prints strings plainly.
  534.  
  535. =item show @blah
  536.  
  537. =item show_scalar $x
  538.  
  539. Like C<warn>, but instead of returning the value from C<warn> it returns its
  540. arguments, so it can be used in the middle of an expression.
  541.  
  542. Note that
  543.  
  544.     my $x = show foo();
  545.  
  546. will actually evaluaate C<foo> in list context, so if you only want to dump a
  547. single element and retain scalar context use
  548.  
  549.     my $x = show_scalar foo();
  550.  
  551. which has a prototype of C<$> (as opposed to taking a list).
  552.  
  553. This is similar to the venerable Ingy's fabulous and amazing L<XXX> module.
  554.  
  555. =item carp
  556.  
  557. =item croak
  558.  
  559. =item confess
  560.  
  561. =item cluck
  562.  
  563. Drop in replacements for L<Carp> exports, that format their arguments like
  564. C<warn>.
  565.  
  566. =item dump @stuff
  567.  
  568. Returns a one line, human readable, concise dump of @stuff.
  569.  
  570. If called in void context, will C<warn> with the dump.
  571.  
  572. Truncates the dump according to C<max_length> if specified.
  573.  
  574. =item dump_as_list $depth, @stuff
  575.  
  576. =item dump_as_pairs $depth, @stuff
  577.  
  578. Dump C<@stuff> using the various formatting functions.
  579.  
  580. Dump as pairs returns comma delimited pairs with C<< => >> between the key and the value.
  581.  
  582. Dump as list returns a comma delimited dump of the values.
  583.  
  584. =item frmat $depth, $value
  585.  
  586. =item format_key $depth, $key
  587.  
  588. =item format_object $depth, $object
  589.  
  590. =item format_ref $depth, $Ref
  591.  
  592. =item format_array $depth, $array_ref
  593.  
  594. =item format_hash $depth, $hash_ref
  595.  
  596. =item format_undef $depth, undef
  597.  
  598. =item format_string $depth, $string
  599.  
  600. =item format_number $depth, $number
  601.  
  602. =item quote $string
  603.  
  604. The various formatting methods.
  605.  
  606. You can override these to provide a custom format.
  607.  
  608. C<format_array> and C<format_hash> recurse with C<$depth + 1> into
  609. C<dump_as_list> and C<dump_as_pairs> respectively.
  610.  
  611. C<format_ref> delegates to C<format_array> and C<format_hash> and does the
  612. C<max_depth> tracking. It will simply stringify the ref if the recursion limit
  613. has been reached.
  614.  
  615. =back
  616.  
  617. =head1 VERSION CONTROL
  618.  
  619. This module is maintained using git. You can get the latest version from
  620. L<http://github.com/nothingmuch/devel-partialdump>.
  621.  
  622. =head1 AUTHOR
  623.  
  624. Yuval Kogman E<lt>nothingmuch@woobling.orgE<gt>
  625.  
  626. =head1 COPYRIGHT
  627.  
  628.     Copyright (c) 2008, 2009 Yuval Kogman. All rights reserved
  629.     This program is free software; you can redistribute
  630.     it and/or modify it under the same terms as Perl itself.
  631.  
  632. =cut
  633.  
  634.